use actix_web::{get, post, web::{self, Query, ServiceConfig}};
use serde::Deserialize;

use crate::{error::AppErr, store::product2::{self, Product2}, web::{codec::{cbor::{new_ok_cbor, Cbor, CborRet}, device_session::notify_product_update, session::Session, user_session::UserSession, Void}, download::{new_download, Download}}};

use super::IdReq;

#[derive(Debug, Deserialize)]
struct CreateReq {
    name: String,
    price: u32,
    #[serde(with = "serde_bytes")]
    image: Box<[u8]>,
}

#[post("/create")]
async fn on_create(_: UserSession, req: Cbor<CreateReq>) -> CborRet<i64> {
    let r = product2::create(&req.name, req.price, &req.image).await?;
    notify_product_update().await?;
    new_ok_cbor( r )
}

#[derive(Debug, Deserialize)]
struct EditReq {
    id: i64,
    name: String,
    price: u32,
    #[serde(with = "serde_bytes")]
    image: Option<Box<[u8]>>,
}

#[post("/edit")]
async fn on_edit(_: UserSession, req: Cbor<EditReq>) -> Result<Void, AppErr> {
    let img: Option<&[u8]> = if let Some(img) = req.image.as_ref() {
        Some(&img)
    } else {
        None
    };
    product2::edit(req.id, &req.name, req.price, img).await?;
    notify_product_update().await?;
    Ok(Void)
}

#[get("/query")]
async fn on_query(_: Session) -> CborRet<Box<[Product2]>> {
    new_ok_cbor( product2::query().await? )
}

#[derive(Debug, Deserialize)]
struct IamgeId {
    image_id: i64,
}

#[get("/get")]
async fn on_get_image(_: UserSession, req: Query<IamgeId>) -> Result<Download, AppErr> {
    let body = product2::get_image(req.image_id).await?;
    Ok(new_download(format!("image_{}", req.image_id), body))
}

#[post("/delete")]
async fn on_delete(_: UserSession, req: Cbor<IdReq>) -> Result<Void, AppErr> {
    product2::delete(req.id).await?;
    notify_product_update().await?;
    Ok(Void)
}

pub fn register(cfg: &mut ServiceConfig) {
    let scope = web::scope("/product2")
    .service(on_create)
    .service(on_edit)
    .service(on_query)
    .service(on_get_image)
    .service(on_delete)
    ;
    cfg.service(scope);
}
